#include "../include/EventLoop.h"
#include "../include/TimeWheel.h" // 在这里包含
#include "../include/Channel.h"   // 在这里包含
#include "EventLoop.h"
// 执行任务池中的所有任务
void EventLoop::RunAllTask()
{
    std::vector<func> f;
    {
        std::unique_lock<std::mutex> _lock(_mutex);
        f.swap(_task_queue);
    }
    for (func &temp : f)
        temp();
}

void EventLoop::WakeUpEventFd()
{
    uint64_t res = 1;
    ssize_t ret = write(_event_fd, &res, sizeof(res));
    if (ret < 0)
    {
        if (errno == EINTR)
        {
            return;
        }
        ERR_LOG("WakeUp eventfd failed: %s", strerror(errno));
        exit(static_cast<int>(EventLoopExitCode::WAKEUP_EVENTFD_FAILED));
    }
}

void EventLoop::ReadEventFd()
{
    uint64_t res = 0;
    ssize_t ret = read(_event_fd, &res, sizeof(res));
    if (ret < 0)
    {
        if (errno == EINTR || errno == EAGAIN)
        {
            return;
        }
        ERR_LOG("Read eventfd failed: %s", strerror(errno));
        exit(static_cast<int>(EventLoopExitCode::READ_EVENTFD_FAILED));
    }
}

int EventLoop::CreateEventFd()
{
    int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
    if (efd < 0)
    {
        ERR_LOG("Create eventfd failed: %s", strerror(errno));
        exit(static_cast<int>(EventLoopExitCode::CREATE_EVENTFD_FAILED));
    }
    return efd;
}

EventLoop::EventLoop()
    : _event_fd(CreateEventFd()),
      _event_channel(new Channel(this, _event_fd)),
      _time_wheel(new TimeWheel(this)),
      _thread_id(std::this_thread::get_id())
{
    _event_channel->SetReadCallBack(std::bind(&EventLoop::ReadEventFd, this));
    _event_channel->EnableRead();
}

void EventLoop::Start()
{
    while (true)
    {
        // 1.事件监控
        std::vector<Channel *> actives;
        _poller.Poll(&actives);
        // 2.事件处理
        for (Channel *&ch : actives)
            ch->HandleEvent();

        RunAllTask();
    }
}

void EventLoop::RunInLoop(const func &f)
{
    if (IsInLoop())
        return f();
    else
        return QueueInLoop(f);
}

void EventLoop::QueueInLoop(const func &f)
{
    {
        std::unique_lock<std::mutex> _lock(_mutex);
        _task_queue.emplace_back(f);
    }
    // 唤醒有可能因为没有事件就绪导致的epoll阻塞
    WakeUpEventFd();
}

void EventLoop::UpdateEvent(Channel *channel)
{
    _poller.UpdateEvents(channel);
}

void EventLoop::RemoveEvent(Channel *channel)
{
    _poller.RemoveEvents(channel);
}

bool EventLoop::IsInLoop()
{
    return std::this_thread::get_id() == _thread_id;
}

void EventLoop::AssertInLoop()
{
    assert(IsInLoop());
}

void EventLoop::TimerAdd(uint64_t id, uint32_t delay, const func &f)
{
    _time_wheel->TimerAdd(id, delay, f);
}

void EventLoop::TimerRefersh(uint64_t id)
{
    _time_wheel->TimerRefersh(id);
}

void EventLoop::TimerCancel(uint64_t id)
{
    _time_wheel->TimerCancel(id);
}
bool EventLoop::HasTimer(uint64_t id)
{
    return _time_wheel->HasTimer(id);
}

EventLoop::~EventLoop()
{
    ::close(_event_fd);
}
